package org.reference.generic.information;

import java.util.ArrayList;
import java.util.List;

import org.reference.generic.Process;
import org.reference.generic.base.Item;
import org.reference.generic.base.Parameter;
import org.reference.generic.base.ReferenceParameter;
import org.reference.generic.base.Manager.OnCompleteListenner;
import org.reference.generic.operator.Add;
import org.reference.generic.operator.Div;
import org.reference.generic.operator.Mul;
import org.reference.generic.operator.Sub;
import org.reference.generic.operator.Node;
import org.reference.generic.operator.NodeFactory;
import org.reference.generic.operator.Function;

/**
 * 
 */
public class Gene extends Item implements Cloneable, Process.OnCompleteListenner{

    /**
     * 
     */
    public Gene(Parameter parameters) {
    	setName("GENE");
    	rootNode = NodeFactory.getRandomNode(parameters.getValueToInt(Parameter.TYPE_MAX_DEPTH),
				parameters.getValueToInt(Parameter.TYPE_DEPTH),
				parameters.getValueToInt(Parameter.TYPE_ARITY));
    }
    
    private OnCompleteListenner onCompleteListenner;
    /**
     * @param onCompleteListenner
     */
    public void setOnCompleteListenner(OnCompleteListenner onCompleteListenner) {
        this.onCompleteListenner = onCompleteListenner;
    }
     
    /**
     * 
     */
   
   private Node rootNode;


	public Node getRootNode() {
		return rootNode;
	}
	
	public List<Process> processList = new ArrayList<Process>();
	
	public void makeProcess(int valueToInt, Parameter parameters, List<ReferenceParameter> rpList){
		
		for(int i =0; i<valueToInt ; i++){
			Process p = new Process();
			p.setName("process "+i);
			p.setOnCompleteListenner(this);
			p.makeSchedule(i, parameters, rpList, this);
			processList.add(p);
			
		}
	}
	
	public double calculateGene(){
		
		Function f = (Function) rootNode;
		f.operation();
		return f.getResult();
		
	}
	
	public void run(){
		
		for(Process pRun : processList){
			pRun.run();
		}
		
	}
	
	public double getAverageFiness(){
		
		double averageFiness=0;
		int nullCheck =0;
		
		for(Process pRun : processList){
			if(pRun.getFitness()!=0){
			averageFiness+=pRun.getFitness();}
			else{
				nullCheck++;
			}
		}
		
		
		return averageFiness/(processList.size()-nullCheck);
		
	}
	
	
	
	
	public void getScheduleFiness(){
	
		
		for(int i=0; i<processList.size();i++){
			System.out.println("프로세스" +i+"스케줄 "+processList.get(i).getFitness());
		}
		
	}
	
	
	 public interface OnCompleteListenner {
	        /**
	         * @param 
	         */
	        public abstract void onComplete(Gene gene);

	    }
	
	@Override
	public void onComplete(Process process) {

	//System.out.println("평균 에버리지 " +getAverageFiness());
	//System.out.println(" 에버리지 " );
	//System.out.println("프로세스 갯수 "+processList.size());
	
	if (onCompleteListenner == null) return;
	onCompleteListenner.onComplete(this);  
	
	}
	
	
}
		